package com.san.common.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import org.springframework.core.io.FileSystemResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;

public class FileUtil {

	/**
	 * 保存上传文件
	 * 
	 * @param stream
	 * @param allpath
	 * @throws IOException
	 */
	public static void saveFileFromInputStream(InputStream stream, String filepath, String fileName)
			throws IOException {
		File file = new File(filepath);
		if (!file.exists()) {
			file.mkdirs();
		}
		FileOutputStream fs = new FileOutputStream(filepath + fileName);
		byte[] buffer = new byte[1024 * 1024];
		int byteread = 0;
		while ((byteread = stream.read(buffer)) != -1) {
			fs.write(buffer, 0, byteread);
			fs.flush();
		}
		fs.close();
		stream.close();
	}

	public static void uploadFile(byte[] file, String filePath, String fileName) throws Exception {
		File targetFile = new File(filePath);
		if (!targetFile.exists()) {
			targetFile.mkdirs();
		}
		FileOutputStream out = new FileOutputStream(filePath + fileName);
		out.write(file);
		out.flush();
		out.close();
	}

	public static boolean deleteFile(String fileName) {
		File file = new File(fileName);
		// 如果文件路径所对应的文件存在，并且是一个文件，则直接删除
		if (file.exists() && file.isFile()) {
			if (file.delete()) {
				return true;
			} else {
				return false;
			}
		} else {
			return false;
		}
	}

	public static String renameToUUID(String fileName) {
		return UUID.randomUUID() + "." + fileName.substring(fileName.lastIndexOf(".") + 1);
	}

	/**
	 * 文件解压
	 * 
	 * @param zipFileName
	 *            压缩文件名
	 * @param outputDirectory
	 *            压缩文件路径
	 * @throws Exception
	 */
	public static void unzip(String zipFileName, String outputDirectory) throws Exception {
		String allPath = outputDirectory + File.separator + zipFileName;
		ZipInputStream in = new ZipInputStream(new FileInputStream(allPath), Charset.forName("gbk"));
		ZipEntry z;
		while ((z = in.getNextEntry()) != null) {
			// System.out.println("unziping " + z.getName());
			if (z.isDirectory()) {
				String name = z.getName();
				name = name.substring(0, name.length() - 1);
				File f = new File(outputDirectory + File.separator + name);
				f.mkdir();
				// System.out.println("mkdir " + outputDirectory +
				// File.separator
				// + name);
			} else {
				File f = new File(outputDirectory + File.separator + z.getName());
				f.createNewFile();
				FileOutputStream out = new FileOutputStream(f);
				int b;
				while ((b = in.read()) != -1)
					out.write(b);
				out.close();
			}
		}
		in.close();
	}

	/**
	 * 获取文件夹下所有文件名，不含文件夹
	 * 
	 * @param path
	 * @return
	 */
	public static List<String> readFolder(String path) {
		List<String> fileList = new ArrayList<String>();
		File file = new File(path);
		File[] tempList = file.listFiles();
		for (int i = 0; i < tempList.length; i++) {
			if (tempList[i].isFile()) {
				fileList.add(tempList[i].getName());
			}
		}
		return fileList;
	}

	/**
	 * 复制文件
	 * 
	 * @param srcPath
	 *            源文件绝对路径
	 * @param destDir
	 *            目标文件所在目录
	 * @param destFileName 新文件名
	 * @return boolean
	 */
	public static boolean copyFile(String srcPath, String destDir, String destFileName) {
		boolean flag = false;

		File srcFile = new File(srcPath);
		if (!srcFile.exists()) { // 源文件不存在
			System.out.println("源文件不存在");
			return false;
		}
		
		String destPath = destDir + destFileName;
		
		if (destPath.equals(srcPath)) { // 源文件路径和目标文件路径重复
			System.out.println("源文件路径和目标文件路径重复!");
			return false;
		}
		File destFile = new File(destPath);
		if (destFile.exists() && destFile.isFile()) { // 该路径下已经有一个同名文件
			System.out.println("目标目录下已有同名文件!");
			return false;
		}

		File destFileDir = new File(destDir);
		if (!destFileDir.exists()) {
			destFileDir.mkdirs();
		}
		try {
			FileInputStream fis = new FileInputStream(srcPath);
			FileOutputStream fos = new FileOutputStream(destFile);
			byte[] buf = new byte[1024];
			int c;
			while ((c = fis.read(buf)) != -1) {
				fos.write(buf, 0, c);
			}
			fis.close();
			fos.close();

			flag = true;
		} catch (IOException e) {
			//
		}

		if (flag) {
			System.out.println("复制文件成功!");
		}

		return flag;
	}

	/**
	 * 删除目录及其下面的所有子文件和子文件夹
	 * 
	 * @param path
	 *            目录的路径
	 */
	public static boolean deleteDirectory(String path) {
		boolean flag = true;
		File dirFile = new File(path);
		if (!dirFile.isDirectory()) {
			return flag;
		}
		File[] files = dirFile.listFiles();
		for (File file : files) { // 删除该文件夹下的文件和文件夹
			// Delete file.
			if (file.isFile()) {
				flag = file.delete();
			} else if (file.isDirectory()) {// Delete folder
				flag = deleteDirectory(file.getAbsolutePath());
			}
			if (!flag) { // 只要有一个失败就立刻不再继续
				break;
			}
		}
		flag = dirFile.delete(); // 删除空目录
		return flag;
	}
	
	/**
	 * 文件下载
	 * 
	 * @param file
	 * @param fileType
	 * @param fileName
	 * @return
	 */
	public static ResponseEntity<FileSystemResource> export(File file) {
		if (file == null) {
			return null;
		}
		HttpHeaders headers = new HttpHeaders();
		headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
		headers.add("Access-Control-Allow-Origin", "*");
		try {
			headers.add("Content-Disposition",
					"attachment; filename=" + URLEncoder.encode(file.getName(), "UTF-8"));
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		headers.add("Pragma", "no-cache");
		headers.add("Expires", "0");
		headers.add("Last-Modified", new Date().toString());
		headers.add("ETag", String.valueOf(System.currentTimeMillis()));

		return ResponseEntity.ok().headers(headers).contentLength(file.length())
				.contentType(MediaType.parseMediaType("application/octet-stream")).body(new FileSystemResource(file));
	}
	
	/**
	 * 文件下载
	 * 
	 * @param file
	 * @param fileType
	 * @param fileName
	 * @return
	 */
	public static ResponseEntity<FileSystemResource> export(File file, String fileType, String fileName) {
		if (file == null) {
			return null;
		}
		HttpHeaders headers = new HttpHeaders();
		headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
		headers.add("Access-Control-Allow-Origin", "*");
		headers.add("FILE_TYPE", fileType);
		try {
			headers.add("Content-Disposition",
					"attachment; filename=" + URLEncoder.encode(fileName, "UTF-8") + "." + fileType);
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		headers.add("Pragma", "no-cache");
		headers.add("Expires", "0");
		headers.add("Last-Modified", new Date().toString());
		headers.add("ETag", String.valueOf(System.currentTimeMillis()));

		return ResponseEntity.ok().headers(headers).contentLength(file.length())
				.contentType(MediaType.parseMediaType("application/octet-stream")).body(new FileSystemResource(file));
	}

	/**
	 * xlsx文件下载
	 * 
	 * @param bytes 文件字节
	 * @param fileName 文件名
	 * @return
	 */
	public static ResponseEntity<byte[]> xlsxExport(byte[] bytes, String fileName) {
		if (bytes == null) {
			return null;
		}
		HttpHeaders headers = new HttpHeaders();
		headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
		headers.add("Access-Control-Allow-Origin", "*");
		try {
			headers.add("Content-Disposition",
					"attachment; filename=" + URLEncoder.encode(fileName, "UTF-8") + ".xlsx");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		headers.add("Pragma", "no-cache");
		headers.add("Expires", "0");
		headers.add("Last-Modified", new Date().toString());
		headers.add("ETag", String.valueOf(System.currentTimeMillis()));

		return ResponseEntity.ok().headers(headers).contentLength(bytes.length)
				.contentType(MediaType.parseMediaType("application/octet-stream")).body(bytes);
	}
}
